package Logica;

import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;
import java.util.ArrayList;

public class ChessTrainer {
    int posFichas[][]=new int[16][2];
    String[]fichas={"p","P","p","P","p","P","p","P","b","B","h","H","q","Q","k","K"};
    ArrayList<int[]> posicionesGeneradas=new ArrayList();
    Hashtable arbolGenerado=new Hashtable();
    Nodo actual;
    int opAplicar[];

    public ChessTrainer() {        
        posFichas=GenerarPosicionesAleatorias();
        arbolGenerado=new Hashtable();
        actual=new Nodo(posFichas, null, null, 0, 0);
        System.out.println("Inicial");
        actual.ImprimirMatriz();
        System.out.println();
        actual.ImprimirMatrizPosiciones();
        System.out.println();
    }
    
    public int [][] getPosiciones(){
        return this.posFichas;
    }
    
    public int[][] GenerarPosicionesAleatorias()
    {
        int x,y;
        int pos[];
        do{
            posicionesGeneradas.clear();
            int i=0;
            while(i<16)
            {
                 x=(int) (Math.random()*6);
                y=(int) (Math.random()*6);
                pos=new int[]{x,y};
                 if(!Contiene(posicionesGeneradas,pos))
                 {
                     posicionesGeneradas.add(pos);
                     posFichas[i]=pos;
                     i++;
                 }
            } 
        }
        while(new Nodo(posFichas, null, null, 0, 0).Jaque(0)||new Nodo(posFichas, null, null, 0, 0).Jaque(1));  
        return posFichas;
    }
    
  
    
    public boolean Contiene(ArrayList<int[]> lista,int pos[]){
        boolean contiene=false;
        for (int i = 0; i < lista.size(); i++) {
            int object[] = lista.get(i);
            if(object[0]==pos[0]&&object[1]==pos[1])
            {
                contiene=true;
                break;
            }
            
        }
        return contiene;
    }
   
   
   int CalcularHeuristica()
   {
       int heuristica = 0;
       return heuristica;
   }
   
//   public Nodo AlgoritmoMinimax(Nodo nodo,int profundidad)
//    {  
//        ArrayList<Nodo> hijos=new ArrayList(); 
//        ArrayList<Double> evaluacionHeuristica=new ArrayList<Double>();
//        //ArrayList<Nodo> decHijos=new ArrayList(); 
//        Nodo decision;
//        int index;
//        int color=nodo.color;
//        hijos=nodo.DeterminarPosiblesJugadas(color);
////        System.out.println("Minimax");
////        actual.ImprimirMatriz();
////        System.out.println();
////        actual.ImprimirMatrizPosiciones();
////        System.out.println();
//        if(hijos.size()>0)
//        {
//           if(actual.profundidad==profundidad)
//            {
//                hijos=actual.DeterminarPosiblesJugadas(color);
//                if(actual.color==0)
//                { 
//                    for (int i = 0; i < hijos.size(); i++) {
//                        Nodo hijo = hijos.get(i);
//                        evaluacionHeuristica.add(hijo.CalcularHeuristica());                    
//                    }
//                    index=DecisionMax(evaluacionHeuristica);
//                    decision=hijos.get(index);
//                }else{
//                    for (int i = 0; i < hijos.size(); i++) {
//                        Nodo hijo = hijos.get(i);
//                        evaluacionHeuristica.add(hijo.CalcularHeuristica());                    
//                    }
//                    index=DecisionMin(evaluacionHeuristica);
//                    decision=hijos.get(index);
//
//                }
//                }else{
//
//                    for (int i = 0; i < hijos.size(); i++) {
//                        Nodo hijo= hijos.get(i);
//                        evaluacionHeuristica.add(AlgoritmoMinimax(hijo, profundidad).heuristica);                    
//                    }
//                    if(actual.color==0)
//                    {
//                       index=DecisionMax(evaluacionHeuristica);
//                       decision=hijos.get(index);
//                    }else{
//                        index=DecisionMin(evaluacionHeuristica);
//                        decision=hijos.get(index);
//                    }
//
//                } 
//        }else decision=actual;
//        
//        return decision;
//    }
    
    
    public Nodo AlgoritmoMinimax(Nodo nodo,int prof)
    {        
        ArrayList<Nodo> hijos=new ArrayList(); 
        ArrayList<Double> evaluacionHeuristica=new ArrayList<Double>();        
        int index;
        int color=nodo.color;
        int estado[][]=new int[17][2];
        System.arraycopy(nodo.posiciones, 0, estado, 0, 16);
        estado[16]=new int[]{0,color};
        String key=estado.toString();        
        Nodo decision=null;
        if(arbolGenerado.containsKey(key))hijos=(ArrayList<Nodo>) arbolGenerado.get(key);
        else{
            hijos=nodo.DeterminarPosiblesJugadas(color);
        }
        if(hijos.size()>0)
        {
            if(nodo.profundidad==prof)
            {
                for (int i = 0; i < hijos.size(); i++) {
                        Nodo hijo = hijos.get(i);
                        evaluacionHeuristica.add(hijo.CalcularHeuristica());
                    }
                if(color==0)
                {
                    index=DecisionMax(evaluacionHeuristica);
                    decision=hijos.get(index);
                }else{
                    index=DecisionMin(evaluacionHeuristica);
                    decision=hijos.get(index);
                }
                    
            }else{
                for (int i = 0; i < hijos.size(); i++) {
                    Nodo hijo = hijos.get(i);
                    evaluacionHeuristica.add(AlgoritmoMinimax(hijo, prof).CalcularHeuristica());
                }
                if(color==0)
                {
                    index=DecisionMax(evaluacionHeuristica);
                    decision=hijos.get(index);
                }else{
                    index=DecisionMin(evaluacionHeuristica);
                    decision=hijos.get(index);
                }
            }
        }else decision=nodo;
        return decision;
    }
    
    public int DecisionMin(ArrayList<Double> hijos)
    {
        int index=0;
        double minimo=Double.MAX_VALUE;
        for (int i = 0; i < hijos.size(); i++) {
            double d = hijos.get(i);
            if(d<minimo)
            {
                minimo=d;
                index=i;
            }
        }
        return index;
    }
    
    public int DecisionMax(ArrayList<Double> hijos)
    {
        int index=0;
        double maximo=Double.MAX_VALUE;
        for (int i = 0; i < hijos.size(); i++) {
            double d = hijos.get(i);
            if(d>maximo)
            {
                maximo=d;
                index=i;
            }
        }
        return index;
    }
    
    public ArrayList<int[]> posiblesMovimientos(int[] pos){
        return actual.GenerarPosiblesMovimientos(pos);
    }
    
    public void Movimiento(int operacionAplicada[])
    {
        int indiceFicha=operacionAplicada[0];
        int nuevasPosiciones[][] = new int[16][2];
        System.arraycopy(actual.posiciones, 0, nuevasPosiciones, 0, 16);
        int x=operacionAplicada[1],y=operacionAplicada[2],index;
        int color=(indiceFicha%2);
        Nodo nuevo = null;
        actual.ImprimirMatriz();
        System.out.println();
        actual.ImprimirMatriz();        
        if(actual.CasillaVacia(new int[]{x,y}))
        {
            nuevasPosiciones[indiceFicha]=new int[]{x,y};
            nuevo=new Nodo(nuevasPosiciones, operacionAplicada, actual, (color+1)%2, actual.profundidad+1);
        }else if(actual.FichaContraria(new int[]{x,y}, color))
        {
            nuevasPosiciones[indiceFicha]=new int[]{x,y};
            index=actual.IndiceFicha(new int[]{x,y});
            nuevasPosiciones[index]=new int[]{-1,-1};
            nuevo=new Nodo(nuevasPosiciones, operacionAplicada, actual, (color+1)%2, actual.profundidad+1);            
        }
        actual=nuevo;
        //actual.ActualizarNodo(nuevo);
        System.out.println("Actual");
        actual.ImprimirMatriz();
        System.out.println();
        actual.ImprimirMatrizPosiciones();
        System.out.println();
    }
    
    public int[] Jugar(int profundidad){
//        ArrayList <Nodo>movs=actual.DeterminarPosiblesJugadas(0);
//        System.out.println("posibles jugadas");
//        for (int i = 0; i < movs.size(); i++) {
//            Nodo nodo = movs.get(i);
//            nodo.ImprimirMatriz();
//            System.out.println("Calcular heuristica: "+nodo.CalcularHeuristica());
//            System.out.println();
//        }
        Nodo decisionMinimax=AlgoritmoMinimax(actual,2);
        System.out.println("decision minimax");
        decisionMinimax.ImprimirMatriz();
        System.out.println("Heuristica decision: "+decisionMinimax.CalcularHeuristica());
        System.out.println();
        decisionMinimax.ImprimirMatrizPosiciones();
        System.out.println();
        int opAplicada[]=decisionMinimax.operacionAplicada;
        System.out.println("Operacion aplicada: "+opAplicada[0]+" , "+opAplicada[1]+" , "+opAplicada[2]);
        return opAplicada;
    }
    
    

}

